package service

import (
	"encoding/base64"
	"encoding/json"
	"smart-flow/server/config"
	"smart-flow/server/logger"
	"smart-flow/server/net"
	"smart-flow/server/utils"
	"strconv"
	"time"

	"go.uber.org/zap"
)

type OpMsg struct {
	SessionId    string `json:"session_id"`
	Action       string `json:"action"`
	SvrPublicKey string `json:"svr_pub_key"`
	Ip           string `json:"ip"`
	Port         int    `json:"port"`
}

type LcMsg struct {
	AppKey       string `structure2value:"app_key"`
	Timestamp    int64  `structure2value:"timestamp"`
	Round        string `structure2value:"round"`
	Sign         string `structure2value:"sign"`
	BusinessType string `structure2value:"business_type"`
	Targets      string `structure2value:"targets"`
	TargetState  string `structure2value:"target_state"`
	FailureTime  int64  `structure2value:"failure_time"`
	SendType     string `structure2value:"send_type"`
	Data         string `structure2value:"data"`
}

type LcClient struct {
	Ip string `json:"ip"`
}

type LcMsgRes struct {
	OnlineTargets  string `json:"online_targets"`  //成功发送在线目标
	Data           string `json:"data"`            //消息数据
	ErrorCount     int    `json:"error_count"`     //失败客户端总数
	StatusInfo     string `json:"status_info"`     //返回结果
	Product        string `json:"product"`         //产品线
	Status         int    `json:"status"`          //返回状态码
	SuccessCount   int    `json:"success_count"`   //成功客户端总数
	OfflineTargets string `json:"offline_targets"` //成功发送离线目标
	MsgState       int    `json:"msg_state"`       //消息推送结果
	MsgStateInfo   string `json:"msg_state_info"`  //消息推送结果说明
	ErrorTargets   string `json:"error_targets"`
	InvalidCount   int    `json:"invalid_count"`
	InvalidTargets string `json:"invalid_targets"`
}

func NotifyUserConnect(sessionId, uid string, index int) bool {
	return notifyUserOp(sessionId, uid, config.LcActionConnect, index)
}

func NotifyUserDisconnect(sessionId, uid string, index int) {
	_ = notifyUserOp(sessionId, uid, config.LcActionDisconnect, index)
	net.ConsoleInstance(index).DelSession(sessionId)
}

func notifyUserOp(sessionId, uid, action string, index int) bool {
	consoleInfo := config.GetConsoleInfo(index)
	opMsgByte, _ := json.Marshal(OpMsg{
		SessionId:    sessionId,
		Action:       action,
		SvrPublicKey: config.AppConfig().Console.PublicKey,
		Ip:           consoleInfo.NetIp,
		Port:         consoleInfo.Port,
	})
	timestamp := time.Now().Unix()
	sign := utils.SHA1Encode(config.AppConfig().Lc.AppSecret + config.LcSalt + strconv.FormatInt(timestamp, 10))
	lcMsg := LcMsg{
		AppKey:       config.AppConfig().Lc.AppKey,
		Timestamp:    timestamp,
		Round:        config.LcSalt,
		Sign:         sign,
		BusinessType: config.LcBusinessType,
		Targets:      uid,
		TargetState:  "1",
		FailureTime:  timestamp + 300,
		SendType:     "0",
		Data:         base64.StdEncoding.EncodeToString(opMsgByte),
	}
	resp, err := utils.Post(&utils.PostOption{
		Url:     config.AppConfig().Lc.Url,
		Params:  utils.StructToValues(&lcMsg),
		Headers: nil,
	})
	if err != nil {
		logger.Logger.Error("[业务] 调用长连接服务失败", zap.Error(err))
		return false
	}
	if resp.StatusCode() != 200 {
		logger.Logger.Error("[业务] 调用长连接服务失败", zap.Int("code", resp.StatusCode()))
		return false
	}
	var lcMsgRes LcMsgRes
	if err = json.Unmarshal(resp.Body(), &lcMsgRes); err != nil {
		logger.Logger.Error("[业务] json反序列化失败", zap.Error(err))
		return false
	}
	if lcMsgRes.Status != 200 {
		logger.Logger.Error("[业务] 长连接服务返回失败", zap.String("resp", lcMsgRes.StatusInfo))
		return false
	}
	return true
}
